/* (C) Copyright 2024, ZWSOFT Co., LTD.(Guangzhou) All Rights Reserved. */
/** @file Parser.cpp
 *  @brief 解析器与评估器
 *  @details 解析，读取源码文件，运行优化后的代码
 */
#include "Parser.hpp"
#include "Function.hpp"
#include <regex>
#include <chrono>
#include <unordered_set>
#include <iostream>
#include <fstream>

using namespace std;

/**
 * @brief 解析源码文件
 * @details 读取源码文件，处理空格（删除多余的，补充缺少的），保存到m_data中
 * @return true:代码正常执行，false:文件读取失败
 */
bool Parser::parse() {
	bool information_got = read_code();		// 读取并整理代码（去除注释，格式化）
	if (!information_got) return false;
	information_got = read_params();		// 读取测试数据
	if (!information_got) return false;
	information_got = set_function_map();	// 设置函数Hash映射表
	if (!information_got) return false;
	set_functions_ptr();	// 设置每个函数内部指针，以便每个函数都能访问其他函数
	return information_got;
}

bool Parser::read_code() {
	std::ifstream file(m_cppName);
	if (!file.is_open()) {
		cerr << "Error: Unable to open file " << m_cppName << endl << endl;
		return false;
	}
	string line;
	while (getline(file, line)) {
		// 1.去掉注释，多余的空格
		if (line.empty()) continue;
		unordered_set<char> symbols = { '[', ']', '{', '}', '(', ')', ',', ';', '.', '&' };
		for (int i = 0; i < line.size() - 1; i++) {
			// 去掉注释
			if (line[i] == '/' && line[i + 1] == '/') {
				line = line.substr(0, i);
				break;
			}
			// 去掉特殊符号前面的空格
			if (symbols.find(line[i + 1]) != symbols.end()) {
				size_t start_blank = i;
				while (line[start_blank] == ' ') --start_blank;
				line.erase(start_blank + 1, i - start_blank);
				i = start_blank + 1;
			}
		}

		// 2.去除首尾的空白字符
		line.erase(0, line.find_first_not_of(" \t\n\r\f\v"));
		line.erase(line.find_last_not_of(" \t\n\r\f\v") + 1);

		// 3.去除分号前面的空白字符
		if (line.empty()) continue;
		if (line.back() == ';') {
			size_t semicolon_pos = line.size() - 1; // 分号的位置是最后一个字符
			// 从分号位置向前删除空白字符
			while (semicolon_pos > 0 && std::isspace(line[semicolon_pos - 1])) {
				line.erase(semicolon_pos - 1, 1); // 删除一个空白字符
				semicolon_pos--; // 更新分号位置
			}
		}
		// 4.运算符+, -, *, /, =前后必须有空格
		for (char op : {'+', '-','='}) {
			size_t pos = 0;
			while ((pos = line.find(op, pos)) != std::string::npos) {
				// 检查符号左侧是否有空格
				if (pos > 0 && !std::isspace(line[pos - 1])) {
					line.insert(pos, " ");
					pos += 2; // 跳过新插入的空格和符号
				}
				else {
					pos += 1; // 跳过符号
				}
				// 检查符号右侧是否有空格
				if (pos < line.size() && !std::isspace(line[pos])) {
					line.insert(pos, " ");
					pos += 1; // 跳过新插入的空格
				}
			}
		}
		// 5.连续多个空格只保留一个（双指针）
		int j = 0;
		for (int i = 0; i < line.size(); i++) {
			if (!std::isspace(line[i])) {
				line[j++] = line[i];
			}
			else if (j <= 0 || !std::isspace(line[j - 1])) {
				line[j++] = ' ';
			}
		}
		line.resize(j); // 调整字符串大小以移除多余的字符
		//65.将 + + 替换为 ++，将 - - 替换为 --
		size_t pos = 0;
		while (pos < line.size()) {
			if (line[pos] == '+' && pos + 2 < line.size() && line[pos + 1] == ' ' && line[pos + 2] == '+') {
				line.replace(pos, 3, "++");
				pos += 2; // 跳过替换后的 "++"
			}
			else if (line[pos] == '-' && pos + 2 < line.size() && line[pos + 1] == ' ' && line[pos + 2] == '-') {
				line.replace(pos, 3, "--");
				pos += 2; // 跳过替换后的 "--"
			}
			else if (line[pos] == '=' && pos + 2 < line.size() && line[pos + 1] == ' ' && line[pos + 2] == '=') {
				line.replace(pos, 3, "==");
				pos += 2; // 跳过替换后的 "=="
			}
			else {
				++pos; // 移动到下一个字符
			}
		}
		// 保存该行代码
		if (line.size() > 1) {
			if (line.front() == '{') {
				m_code.emplace_back("{");
				if (line.back() == '{') {
					m_code.emplace_back(line.substr(1, line.size() - 2));
					m_code.emplace_back("{");
				}
				else if (line.back() == '}') {
					m_code.emplace_back(line.substr(1, line.size() - 2));
					m_code.emplace_back("}");
				}
				else {
					m_code.emplace_back(line.substr(1));
				}
			}
			else if (line.front() == '}') {
				m_code.emplace_back("}");
				if (line.back() == '{') {
					m_code.emplace_back(line.substr(1, line.size() - 2));
					m_code.emplace_back("{");
				}
				else if (line.back() == '}') {
					m_code.emplace_back(line.substr(1, line.size() - 2));
					m_code.emplace_back("}");
				}
				else {
					m_code.emplace_back(line.substr(1));
				}
			}
			else {
				if (line.back() == '{') {
					m_code.emplace_back(line.substr(0, line.size() - 1));
					m_code.emplace_back("{");
				}
				else if (line.back() == '}') {
					m_code.emplace_back(line.substr(0, line.size() - 1));
					m_code.emplace_back("}");
				}
				else {
					m_code.emplace_back(line);
				}
			}
		}
		else if (line.size() == 1) {
			m_code.emplace_back(line);
		}
	}
	return true;
}
bool Parser::read_params() {
	std::ifstream file(m_txtName);
	if (!file.is_open()) {
		cout << "Error: Unable to open file " << m_txtName << endl;
		return false;
	}
	std::string line;
	while (std::getline(file, line)) {
		// 去除首尾的空白字符
		line.erase(0, line.find_first_not_of(" "));
		line.erase(line.find_last_not_of(" ") + 1);
		if (line.empty()) continue;
		// 解析括号内的数据
		size_t start = line.find('(');
		size_t end = line.find(')');
		if (start == std::string::npos || end == std::string::npos) {
			cout << "parameter Parse Error";
			return false;
		}

		std::string numbersStr = line.substr(start + 1, end - start - 1);
		std::istringstream numbersStream(numbersStr);
		std::vector<string> numbers;
		std::string numberStr;
		while (std::getline(numbersStream, numberStr, ',')) {
			if (!numberStr.empty()) {
				numbers.emplace_back(numberStr);
			}
		}

		// 解析括号外的数据
		size_t lastComma = line.find_last_of(',');
		size_t lastOpenBrace = line.find_last_of(']');
		if (lastComma == std::string::npos) {
			cout << "given_results Parse Error";
			return false;
		}
		std::string lastNumberStr = line.substr(lastComma + 1, lastOpenBrace - lastComma - 1);
		m_givenResults.emplace_back(lastNumberStr);

		// 将解析后的数据存储到 params 中
		m_params.emplace_back(numbers);
	}
	return true;
}
bool Parser::set_function_map() {
	const vector<string>& code = m_code;
	size_t start = 0, len = code.size();
	int numsOfBlocks = 0;
	bool functionBegin = false;
	bool mainFunc_got = false;
	std::vector<int> func_lines;
	for (size_t i = 0; i < len; ++i) {
		if (code[i].find(";") == string::npos) {	// 没有分号,说明是函数定义
			if (code[i].size() > 2) {
				start = i;
				if (!mainFunc_got)
					mainFunc_got = code[i].find("mainFunc") != string::npos;  	// 是主函数
			}
		}
		else {	// 有分号，说明是代码语句,或者函数申明
			if (functionBegin) {		// 代码语句
				for (auto& func : m_funcMap) {
					if (code[i].find(func.second.get_name()) != string::npos) {  // 此行涉及函数调用
						func_lines.emplace_back(i - start);
					}
				}
			}
			else {		// 函数申明
				if (code[i].size() > 2) {
					Function func(code[i]);
					m_funcMap.emplace(std::make_pair(func.get_full_name(), func));
				}
			}
		}
		if (code[i].find("{") != string::npos) {
			functionBegin = true;
			numsOfBlocks++;
		}
		if (code[i].find("}") != string::npos)
			numsOfBlocks--;
		if (functionBegin && numsOfBlocks == 0) {
			Function func(code, start, i + 1);
			const string& func_name = func.get_name();
			m_funcNameSet.emplace(func_name);
			const string& func_full_name = func.get_full_name();
			if (m_funcMap.find(func_full_name) == m_funcMap.end()) {  // hashmap中不存在该函数，则加入
				m_funcMap.emplace(std::make_pair(func.get_full_name(), func));

			}
			else {	// hashmap中已存在该函数，说明被声明过
				m_funcMap[func_full_name] = func;
			}
			if (m_mainFunc == nullptr && mainFunc_got) {  // main函数未被设置，且找到了main函数
				m_mainFunc = &m_funcMap[func.get_full_name()];
			}
			functionBegin = false;
		}
	}
	if (!m_mainFunc) {
		cout << "Error: mainFunc undefined!" << endl;
	}

	return true;
}

void Parser::set_functions_ptr() {
	for (auto& func : m_funcMap) {
		func.second.set_funcs_ptrs(&m_funcMap, &m_funcNameSet);
	}
}

bool Parser::evaluate() {
	reset();
	size_t sumOfCase = m_params.size();
	for (size_t i = 0; i < m_params.size(); i++) {
		if (m_mainFunc != nullptr) {
			string result = m_mainFunc->run(m_params[i], m_funcMap);			// 运行主函数
			if (result == "error") {
				cout << "Error: " << m_funcMap[m_mainFunc->get_full_name()].get_name() << "() return error!" << endl;
				return false;
			}
			m_results.emplace_back(result);	// 保存结果
		}
		else {
			cout << "No main function found!" << endl;
			return false;
		}
	}
	return true;
}
